package io.youngledo.usb.task;

import java.util.function.Consumer;

/**
 * 通用进度更新器 - 消除ProgressInputStream和ProgressOutputStream的重复代码
 */
public class ProgressUpdater {

    private final ProgressTracker progressTracker;
    private final Consumer<Long> progressCallback;
    private long totalBytesProcessed = 0;
    private long lastReportedBytes = 0;
    private final long reportInterval;
    private final Runnable onCancelAction;

    /**
     * 使用ProgressTracker构造
     */
    public ProgressUpdater(ProgressTracker progressTracker, Runnable onCancelAction) {
        this.progressTracker = progressTracker;
        this.progressCallback = null;
        this.reportInterval = 64 * 1024; // 每64KB报告一次进度
        this.onCancelAction = onCancelAction;
    }

    /**
     * 使用回调函数构造
     */
    public ProgressUpdater(Consumer<Long> progressCallback, Runnable onCancelAction) {
        this.progressTracker = null;
        this.progressCallback = progressCallback;
        this.reportInterval = 64 * 1024;
        this.onCancelAction = onCancelAction;
    }

    /**
     * 更新进度
     */
    public void updateProgress(long bytesProcessed) {
        totalBytesProcessed += bytesProcessed;

        // 为了性能，不每次都报告进度，而是累积到一定量再报告
        if (totalBytesProcessed - lastReportedBytes >= reportInterval ||
            (progressTracker != null && progressTracker.isCancelled())) {

            if (progressTracker != null) {
                progressTracker.addProcessedBytes(totalBytesProcessed - lastReportedBytes);

                // 检查是否被取消
                if (progressTracker.isCancelled()) {
                    if (onCancelAction != null) {
                        onCancelAction.run();
                    }
                }
            }

            if (progressCallback != null) {
                progressCallback.accept(totalBytesProcessed - lastReportedBytes);
            }

            lastReportedBytes = totalBytesProcessed;
        }
    }

    /**
     * 完成进度更新 - 确保所有剩余进度都被报告
     */
    public void finalizeProgress() {
        if (totalBytesProcessed > lastReportedBytes) {
            if (progressTracker != null) {
                progressTracker.addProcessedBytes(totalBytesProcessed - lastReportedBytes);
            }
            if (progressCallback != null) {
                progressCallback.accept(totalBytesProcessed - lastReportedBytes);
            }
            lastReportedBytes = totalBytesProcessed;
        }
    }

    public long getTotalBytesProcessed() {
        return totalBytesProcessed;
    }
}